#ifndef _083E83F7_8898_4CDF_9B15_FF1FD15DE369
#define _083E83F7_8898_4CDF_9B15_FF1FD15DE369

#include "depends/incfile.h"

namespace x2lib
{
    class SysUtil
    {
    public:
        // 此类函数声明不能加static
        static void RedirectIOToConsole();
        static int ReadLine(char buff[], bool mode = 0);

        /*************************************************************************
        ** Desc     : PrintW
        **				+=================+
        **				|      标题       |
        **				|-----------------|
        **				| 内容1           |
        **				| 内容2           |
        **				|-----------------|
        **				|  1.确定         |
        **              |  2.取消         |
        **				|-----------------|
        **				|      腾讯       |
        **				^^^^^^^^^^^^^^^^^^^
        ** Param    : [in] pBuff 缓冲区。为NULL时返回所需nBuff大小
        **		    : [in] pTitle 标题。自动居中，不可包含换行符，会自动换行
        **          : [in] pContent 内容。最多不能超过16个换行符，且每行最多128个字符
        **          : [in] pTips 提示。最多不能超过16个换行符，且每行最多128个字符
        **          : [in] pAppVer 软件名或版权。不可包含换行符
        **          : [in] nWidth 字符窗口宽度。小于5时取默认值，同时如果设置或最
        **					终内部计算出的nWidth大于当前控制台窗口最大宽度，将会显示凌乱
        ** Return   : 返回所需nBuff大小
        ** Author   : xktesla
        *************************************************************************/
        static int PrintW(char *pBuff, const char *pTitle, const char *pContent, const char *pTips = "", const char *pAppVer = nullptr, int nWidth = 0);

        /*************************************************************************
        ** Desc		: 获取格式化时间字串
        ** Param	: [in] szDt 用来保存格式化后的字串
        **			: [in] nDt szDt的大小
        **			: [in] tick 单位秒，0表示自格林威治[0时区]时间1970年01月01日00时00分00秒算起的秒数
        **			: [in] szFmt 用来格式化的常量字串【%Y-%m-%d %H:%M:%S】【%Y-%m-%d %H:%M】【%m-%d %H:%M:%S】
        **              【%Y-%m-%d】【%H:%M:%S】【%m-%d】【%H:%M】
        **			: [in] isUtc 是否获取基于UTC的时间，否则返回当前时区的时间
        ** Return	: 返回szDt
        ** Author	: xktesla@2017-2-26 13:03:10
        *************************************************************************/
        static char *GetFmtDateTime(char *szDt, int nDt, uint64_t tick = 0, const char *szFmt = "%Y-%m-%d %H:%M:%S", bool isUtc = false);

        /**
        * @brief        获取字符串时间对应的秒数，基于UTC 1970年01月01日00时00分00秒
        * @param[in]    szDt 用来保存格式化后的字串，若为NULL则获取当前时间，若为nullptr则默认为当前时间，且此时根据szFmt将未指定的低位抹零，未指定的高位不抹零
        * @param[out]   pWDay 周几（0-周日）
        * @param[in]    szFmt 缺少的位将以0处理，只支持以下7种【%Y-%m-%d %H:%M:%S】【%Y-%m-%d %H:%M】【%m-%d %H:%M:%S】【%Y-%m-%d】【%H:%M:%S】【%m-%d】【%H:%M】
        * @return       返回字符串时间对应的秒数
        * @author       xuekai@2021-12-9
        */
        static uint32_t GetDateTimeTick(const char *szDt = nullptr, uint8_t* pWDay = nullptr, const char* szFmt = "%Y-%m-%d %H:%M:%S");

        /*************************************************************************
        ** Desc		: 获取自系统启动以来的秒数。
        ** Param	: [in] isMill 是否以毫秒表示
        ** Return	: 返回对应的秒数或毫秒数
        ** Author	: xktesla@2017-2-26 13:03:10
        *************************************************************************/
        static uint64_t GetCurrentTick(bool isMill = true);

        /*************************************************************************
        ** Desc		: 返回[0,nMax)之间的一个整数
        ** Param	: [in]
        ** Return	: 返回[0,nMax)之间的一个整数
        ** Author	: xktesla@2017-2-26 13:03:10
        *************************************************************************/
        static int Random(int nMax);

        /*************************************************************************
        ** Desc		: 生成一个UUID
        ** Param	: [in] len
        ** Return	: 16进制形式的字符串
        ** Author	: xktesla@2020-11-3 15:52:17
        *************************************************************************/
        static std::string GenUUID(const unsigned int len);

        /*************************************************************************
        ** Desc		: 将iCurSize扩展为nAlignSize的整倍数
        ** Param	: [in] iCurSize 被检测的大小
        **			: [in] nAlignSize 对其值
        ** Return	: 返回值扩展后的大小，是nAlignSize的整倍数，若iCurSize<=0，则返回0
        ** Author	: xktesla@2017-2-26 13:03:10
        *************************************************************************/
        static int AlignUP(int iCurSize, unsigned int nAlignSize);

        /*************************************************************************
        ** Desc		: 判断两个区间是否有交集
        ** Param	: [in] addr1
        **			: [in] len1
        **			: [in] addr2
        **			: [in] len2
        ** Return	: true/false
        ** Author	: xktesla@2019-8-15 22:44:32
        *************************************************************************/
        static bool IsOverlap(int addr1, int len1, int addr2, int len2);


        /*************************************************************************
        ** Desc		: 查找pFind在pData中的地址
        ** Param	: [in] pData 源数据
        **			: [in] nData 
        **			: [in] pFind 欲搜索的数据
        **			: [in] nFind 
        **			: [in] iWhich 0表示最后一次出现的地址，否则表示表示第iWhich次出现的地址
        ** Return	: nullptr表示未找到
        ** Author	: xktesla@2016-10-30
        *************************************************************************/
        static uint8_t* FindBytes(const void *pData, uint32_t nData, void *pFind, uint32_t nFind, int iWhich = 1);

        //static void ReplaceBytes(void *pDataAddr, void *newArr, int arrLen);
        /*************************************************************************
        ** Desc		: 将pData中所有oldArr替换为newArr，等长替换
        ** Param	:
        ** Return	: 替换了几处
        ** Author	: xktesla@2016-11-26
        *************************************************************************/
        static int ReplaceBytes(void *pData, int nData, const void *oldArr, const void *newArr, int arrLen);
        /*************************************************************************
        ** Desc		: 将pData中所有oldArr替换为newArr，并存储在pDatanew
        ** Param	: [in] pData
        **			: [in] nData
        **			: [in] oldArr
        **			: [in] oldLen
        **			: [in] newArr
        **			: [in] newLen
        **			: [in] pDatanew
        **			: [in/out] pnDatanew 输入pDatanew的大小，输出pDatanew被填充的大小，可能大于或小于nData
        ** Return	: 是否搜索完毕
        ** Author	: xktesla@2016-11-26 22:10:15
        *************************************************************************/
        static bool ReplaceBytes(char *pData, uint32_t nData, const void *oldArr, uint32_t oldLen, const void *newArr, uint32_t newLen, char *pDatanew, uint32_t *pnDatanew, bool isIgnoreCase = false);

        /**
        * @brief        获取当前进程工作路径，注意多线程安全
        * @param[in]    mode 0进程全路径，1不包含进程名，2只有进程名
        * @param[in]    buff 保存结果的缓冲区，若nullptr则使用函数内静态内存保存，此时多线程不安全
        * @return       得到的结果，nullptr表示失败
        * @author       xktesla
        */
        static const char* GetWorkDir(uint8_t mode = 0, char* buff = nullptr, uint32_t bufflen = 0);

        static bool IsZero(float fVal);
        static bool IsZero(double dVal);

        /**
        * @brief        比较两个字符串版本号的大小，位数多的大于位数小的
        * @param[in]    pszVer1 如1.1.1.1
        * @param[in]    pszVer2 如1.1.1.1
        * @return
        * @author       xuekai@2022-01-19
        */
        static int CompareVer(const char* pszVer1, const char* pszVer2);

        /**
        * @brief        设置/获取版本信息（实际是附加到文件末）
        * @param[in]    pszFile 目标文件
        * @param[in]    pszVerNum 版本号
        * @param[in]    pszVerTips 更新内容
        * @return
        * @author       xuekai@2022-2-25
        */
        static bool SetAppVer(const char* pszFile, const char* pszVerNum, const char* pszVerTips = "");
        static const char* GetAppVer(const char* pszFile, char szTips[] = nullptr);
        static bool DelAppVer(const char* pszFile);

        static bool IsEnANSI(const char* pszStr);
    };

}

#endif

